package org.sjs.dreamfly.biz.movie.detail

import kotlinx.coroutines.launch
import org.sjs.dreamfly.biz.movie.MovieConstants
import org.sjs.dreamfly.common.base.BaseViewModel
import org.sjs.dreamfly.common.util.PhemonUtils
import org.sjs.dreamfly.data.AppDataBase
import org.sjs.dreamfly.model.HistoryItem
import org.sjs.dreamfly.model.MovieInfo
import org.sjs.dreamfly.model.ResourceType
import org.sjs.dreamfly.model.VideoInfo
import org.sjs.dreamfly.player.IPlayerDataProvider
import java.util.concurrent.atomic.AtomicBoolean

class MovieDetailViewModel: BaseViewModel(), IPlayerDataProvider {

    private var selectedVideoInfo: VideoInfo? = null
    private var firstVideoInfo: VideoInfo? = null
    private var movieInfo: MovieInfo? = null
    private var historyItem: HistoryItem? = null
    private val videoInfoDao by lazy { AppDataBase.getDatabase().videoDao() }
    private lateinit var videoUrlLoadDelegate: ((pageUrl: String) -> Unit)
    private lateinit var sniffStatus: SniffStatus

    fun getMovieInfo(): MovieInfo? {
        return movieInfo
    }

    fun useSniffStatus(channelType: String): SniffStatus {
        sniffStatus = SniffStatus(channelType)
        return sniffStatus
    }

    fun getSniffStatus(): SniffStatus {
        return sniffStatus
    }

    override fun getVideoList(): MutableList<VideoInfo> {
        return movieInfo?.videoList?: mutableListOf()
    }

    override fun loadVideoUrl(index: Int) {
        select(index)
        movieInfo?.videoList?.get(index)?.refer?.let { url->
            videoUrlLoadDelegate(url)
        }
    }

    fun onPlayInfoLoaded(url: String, refer: String?) {
        if (refer?.startsWith("https://m.ixigua.com/video/") == true) {
            val id = refer.split("?").firstOrNull()
                ?.replace("https://m.ixigua.com/video/", "")
            if (id == movieInfo?.id) {
                onFirstPlayInfoLoaded(url, refer)
            } else {
                if (selectedVideoInfo?.videoId == id) {
                    selectedVideoInfo?.videoUrl = url
                }
                movieInfo?.videoList?.find { it.videoId == id }?.let {
                    mainScope.launch {
                        videoInfoDao.updateOrInsert(it)
                    }
                }
            }
        }
    }

    private fun onFirstPlayInfoLoaded(url: String, refer: String?) {
        if (firstVideoInfo != null) {
            return
        }
        firstVideoInfo = VideoInfo(
            videoUrl = url,
            refer = refer,
            videoId = "${movieInfo?.id}_0",
            movieId = movieInfo?.id,
            parent = movieInfo
        )
        if (movieInfo?.isSingle() == true) {
            selectedVideoInfo = firstVideoInfo
            movieInfo?.videoList?.add(firstVideoInfo!!)
            mainScope.launch {
                videoInfoDao.updateOrInsert(firstVideoInfo!!)
            }
        }
    }

    fun onPlayListLoaded(videoList: List<VideoInfo>): Boolean {
        if (movieInfo?.videoList.isNullOrEmpty()) {
            movieInfo?.videoList?.addAll(videoList)
            mainScope.launch {
                movieInfo?.videoList?.forEachIndexed { index, videoInfo ->
                    videoInfo.movieId = movieInfo?.id
                    videoInfo.parent = movieInfo
                    videoInfo.nid = index + 1
                    if (index == 0 &&
                        videoInfo.videoUrl.isNullOrEmpty() &&
                        firstVideoInfo != null &&
                        !firstVideoInfo?.videoUrl.isNullOrEmpty()) {
                        videoInfo.videoUrl = firstVideoInfo?.videoUrl
                        firstVideoInfo = videoInfo
                    }
                    videoInfoDao.updateOrInsert(videoInfo)
                }
            }
            select(historyItem?.movieProgress?:0)
            return true
        }
        return false
    }

    suspend fun onMovieLoaded(movieInfo: MovieInfo?) {
        this.movieInfo = movieInfo
        historyItem = AppDataBase.getDatabase(PhemonUtils.getApplication()).historyDao()
            .query(ResourceType.MOVIE, movieInfo!!.id).firstOrNull()
        if (movieInfo.videoList.isEmpty()) {
            onPlayListLoaded(videoInfoDao.sortedQuery(movieInfo.id))
        }
    }

    fun getCurrent(): Int {
        val index = movieInfo?.videoList?.indexOfFirst { it.videoId == selectedVideoInfo?.videoId }
        return (if (index == -1 && historyItem != null) {
            historyItem!!.movieProgress
        } else index?:0)
    }

    fun getCurrentVideoInfo(): VideoInfo? {
        return selectedVideoInfo?:firstVideoInfo
    }

    fun setVideoUrlLoadDelegate(videoUrlLoadDelegate: ((pageUrl: String) -> Unit)) {
        this.videoUrlLoadDelegate = videoUrlLoadDelegate
    }

    fun isPlayListPrepared(): Boolean {
        if (movieInfo?.videoList?.isNotEmpty() == true) {
            return movieInfo?.videoList?.size!! >= (movieInfo?.totalVideoCount ?: 0)
        }
        return false
    }

    fun select(index: Int) {
        selectedVideoInfo = movieInfo?.videoList?.getOrNull(index)
    }

    class SniffStatus(private val channelType: String) {
        private var isSniffing = AtomicBoolean(false)
        private var isPlayInfoSniffed = AtomicBoolean(false)
        private var isPlayListSniffed = AtomicBoolean(false)
        fun toBegin() {
            isSniffing.set(true)
        }

        fun recordPlayInfoSniffed() {
            isPlayInfoSniffed.set(true)
            if (channelType == MovieConstants.CHANNEL_TYPE_OTHER_CHIHUAYU) {
                isSniffing.set(false)
            } else if (isPlayListSniffed.get()) {
                isSniffing.set(false)
            }
        }

        fun recordPlayListSniffed() {
            isPlayListSniffed.set(true)
            if (isPlayInfoSniffed.get()) {
                isSniffing.set(false)
            }
        }

        fun isSniffing(): Boolean {
            return isSniffing.get()
        }
    }
}